package com.iotcomm.protocol;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 消息编解码器
 * 处理TCP粘包/拆包问题
 * 协议格式：[4字节长度][JSON消息体]
 */
public class MessageCodec extends ByteToMessageCodec<Message> {
    private static final Logger logger = LoggerFactory.getLogger(MessageCodec.class);
    
    // 消息头长度（4字节用于存储消息体长度）
    private static final int HEADER_LENGTH = 4;
    // 最大消息长度（1MB）
    private static final int MAX_MESSAGE_LENGTH = 1024 * 1024;
    
    /**
     * 编码：将Message对象编码为ByteBuf
     * @param ctx 通道上下文
     * @param msg 要编码的消息
     * @param out 输出缓冲区
     */
    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) {
        try {
            // 将消息序列化为JSON字符串
            String jsonMessage = msg.toJson();
            byte[] messageBytes = jsonMessage.getBytes(StandardCharsets.UTF_8);
            
            // 写入消息长度（4字节）
            out.writeInt(messageBytes.length);
            // 写入消息体
            out.writeBytes(messageBytes);
            
            logger.debug("编码消息: 长度={}, 内容={}", messageBytes.length, jsonMessage);
        } catch (Exception e) {
            logger.error("消息编码失败", e);
            throw new RuntimeException("消息编码失败", e);
        }
    }
    
    /**
     * 解码：将ByteBuf解码为Message对象
     * @param ctx 通道上下文
     * @param in 输入缓冲区
     * @param out 输出列表
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        try {
            // 检查是否有足够的字节读取消息头
            if (in.readableBytes() < HEADER_LENGTH) {
                return; // 等待更多数据
            }
            
            // 标记当前读取位置
            in.markReaderIndex();
            
            // 读取消息长度
            int messageLength = in.readInt();
            
            // 验证消息长度
            if (messageLength <= 0 || messageLength > MAX_MESSAGE_LENGTH) {
                logger.error("无效的消息长度: {}", messageLength);
                ctx.close();
                return;
            }
            
            // 检查是否有足够的字节读取完整消息
            if (in.readableBytes() < messageLength) {
                // 重置读取位置，等待更多数据
                in.resetReaderIndex();
                return;
            }
            
            // 读取消息体
            byte[] messageBytes = new byte[messageLength];
            in.readBytes(messageBytes);
            
            // 将字节数组转换为字符串
            String jsonMessage = new String(messageBytes, StandardCharsets.UTF_8);
            
            // 反序列化为Message对象
            Message message = Message.fromJson(jsonMessage);
            
            logger.debug("解码消息: 长度={}, 内容={}", messageLength, jsonMessage);
            
            // 添加到输出列表
            out.add(message);
            
        } catch (Exception e) {
            logger.error("消息解码失败", e);
            // 关闭连接以防止进一步的错误
            ctx.close();
        }
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        logger.error("编解码器异常", cause);
        ctx.close();
    }
}